#File: rondamon_interpret_test.py - Rondamon interpreter unit testing
#JGordon & Co

from unittest import TestCase, makeSuite, TextTestRunner
import sys
from StringIO import StringIO
from rondamon import RondamonException
from rondamon_interpreter import RdmReturnException
from rondamon_interpreter import create_table, eval_expr, \
    execute_print, execute_if, execute_while, execute_return, execute_if, execute_assign, execute_statements,execute_fu, execute_call, execute_index, interpret


class RondamonInterpretTetsCase(TestCase):

    def setUp(self):
        self.output = StringIO()
        sys.stdout = self.output
        
    def tearDown(self):
        self.output.close()
        sys.stdout = sys.__stdout__
	
    def testEvalExpr(self):
        'eval_expr test'
        table = {'alpha':10, 'beta': [4,2,3]}
        self.assertEquals(eval_expr(table, 5), 5)
        self.assertEquals(eval_expr(table, 'alpha'), 10)
	self.assertEquals(eval_expr(table, '"hola mundo"'), 'hola mundo')
	self.assertEquals(eval_expr(table, ['-', 'alpha']), -10)
        self.assertEquals(eval_expr(table, ['#', 'beta']), 3)
	self.assertEquals(eval_expr(table, ['#', [1,2,3]]), 3)
	self.assertEquals(eval_expr(table, ['index', [1,2], 0]), 1)
	self.assertEquals(eval_expr(table, ['index', 'beta', 0]), 4)
	
    def testExecuteAssign(self):
        'assign test'
        table = {'alpha':10, 'beta': [4,2,3]}
	execute_assign(table,['x',5])
	execute_print(table, 'x')
	self.assertEquals(self.output.getvalue(), '5\n')
	
    def testExecutePrint(self):
        'execute_print test'
        table = {'alpha':10, 'beta': -5}
        execute_print(table, [5])
        execute_print(table, [['*', 'alpha', 10]])
        execute_print(table, [['<', 'alpha', 'beta']])
        self.assertEquals(self.output.getvalue(), '5\n100\nFalse\n')
	
    def testExecuteIf(self):
        'execute_if test'
        table = {'alpha':10, 'beta': -5}
        execute_if(table, [5, [['print', 1]]])
        execute_if(table, [0, [['print', 1]]])
        execute_if(table, [['<', 'beta', 'alpha'], [['print', 100]]])
        self.assertEquals(self.output.getvalue(), '1\n100\n')
	
    def testExecuteWhile(self):
        'execute_while test'
        table = {'alpha':10, 'beta': -5}
        execute_while(table, [['<','beta',0], [['=','beta',['+','beta',1]],['print', 'beta']]])
        self.assertEquals(self.output.getvalue(), '-4\n-3\n-2\n-1\n0\n')
	
    def testExecuteFu(self):
        'execute_fu test'
        table = {'alpha':10, 'beta': -5}
        execute_fu(table, ['hola',[],[['print', 1]]])
	execute_print(table, ['hola'])
	self.assertEquals(self.output.getvalue(), "[[], [['print', 1]]]\n")
	
    def testExecuteCall(self):
        'execute_call test'
        table = {'alpha':10, 'beta': -5}
        execute_fu(table, ['hola',['x'],[['while',['<','beta',0], [['=','beta',['+','beta',1]],['print', 'beta']]]]])
	execute_call(table, ['hola',[10]])
	self.assertEquals(self.output.getvalue(), "-4\n-3\n-2\n-1\n0\n")

    def testExecuteStatement(self):
        'execute_statement test'
        table = {'alpha':10, 'beta': -5}
	execute_fu(table, ['hola',['x'],[['print', 'x']]])
	execute_statements(table,[['call','hola',[1]]])
	self.assertEquals(self.output.getvalue(), "1\n")
    
    def testExecuteReturn(self):
	'execute_return test'
	table = {'alpha':10, 'beta': -5}
	self.assertRaises(RdmReturnException, execute_return, table,[['*', 'alpha', 10]])

    def testInterpret(self):
        'interpret test'
        cadena = '''
        fu factorial(n)
                result = 1
                while n > 0 do
                    result = result * n
                    n = n - 1
                end
                print result
        end

        factorial(6)
	'''
	interpret(cadena)
	self.assertEquals(self.output.getvalue(), '720\n')                 
	
    def testInterpret2(self):
        'interpret test 2 '
	cadena = '''
	fu mayorLista(lst)
                aux = 0
                mayor = lst[0]
                while aux < #lst do
                    if lst[aux] > mayor then
                        mayor = lst[aux]
                    end
                    aux = aux + 1
                end
                print mayor
	end
	
	mayorLista([1,5,201,8,3,1,0])
	
	'''
	interpret(cadena)
	self.assertEquals(self.output.getvalue(), '201\n')                 
	
    def testInterpret3(self):
	'interpret test 3'
	cadena = '''
	fu factorial(n)
                result = 1
                while n > 0 do
                    result = result * n
                    n = n - 1
                end
                return result
        end

        x = factorial(5)
        print x
	'''
	interpret(cadena)
	self.assertEquals(self.output.getvalue(), '120\n')
	
    def testInterpret4(self):
	'interpret test 4'
	cadena = '''
	x = "hola mundo"
	lista = [1,2,3,4]
	y = 1
	
	fu testif()
	    if #x == #lista then
	        print "if"
	    else
	        print "else"
	    end
	end

        testif()

        while y< 10 do
            if(y==7) then 
                break 
            end
            print y
            y = y + 1
        end
        
        if mod(3,2)==1 then print mod(3,2) end
        print "end of test"
	
	'''
	interpret(cadena)
	self.assertEquals(self.output.getvalue(),'else\n1\n2\n3\n4\n5\n6\n1\nend of test\n')

    def testFunctions1(self):
        'Python functions test1'
        cadena = '''
        print mod(17,4)
        print pow(2,5)
        print isnumber(3)
        print isnumber("hola")
        print isstring("hola")
        print isstring(3)
        print tostring(3)
        print tonumber("23")
        --print ceil(2.12)
        --print floor(3.1)
        '''
        interpret(cadena)
	self.assertEquals(self.output.getvalue(), '1\n32\nTrue\nFalse\nTrue\nFalse\n3\n23\n')

    def testFunctions2(self):
        'Python functions test2'
        cadena = '''
        x = [1,2,3,4,5]
        lappend(x,9)
        linsert(x,0,0)
        lremove(x,4)
        lsort(x)
        lreverse(x)
        print x
        
        --y = lpop(x)
        --print y
        --print x
        --print lindex(x,9)
        --print lmax(x)
        --print lmin(x)
        
        '''
        interpret(cadena)
	self.assertEquals(self.output.getvalue(), '[9, 5, 3, 2, 1, 0]\n')
        
    def testPersistence(self):
        'Persistence functions test'
        cadena = '''
        
        set_persistent("prueba", 1234)
        print get_persistent("prueba")
        
        set_persistent("prueba2", "hola")
        print get_persistent("prueba2")

        '''

        interpret(cadena)
	self.assertEquals(self.output.getvalue(), "[1234]\n['hola']\n")

    def testWebFunctions(self):
        'WebFunctions test'
        infodic = {'headers': ['Host: localhost:8080', 'User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.14) Gecko/20080404 Firefox/2.0.0.14', 'Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5', 'Accept-Language: en-us,en;q=0.5', 'Accept-Encoding: gzip,deflate', 'Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7', 'Keep-Alive: 300', 'Connection: keep-alive', 'Referer: http://localhost:8080/form.html'], 'parameters': ['alfa=hola', 'alfa=hola2', 'beta=mundo', 'gamma=cruel', 'boton=Submit+Query']}
        
        cadena = '''
        alfa = get_parameter_value("alfa")
        beta = get_parameter_value("beta")
        gamma = get_parameter_value("gamma")

        alfavalues = get_parameter_values("alfa")
        parameters = get_parameter_names()
        
        Host = get_header_value("Host")
        Lang = get_header_value("Accept-Language")

        headers = get_header_names()
        
        print alfa
        print beta
        print gamma
        print alfavalues
        print parameters
        print Host
        print Lang
        print headers
        
        '''
        interpret(cadena,infodic)
        self.assertEquals(self.output.getvalue(), "hola\nmundo\ncruel\n['hola', 'hola2']\n['hola', 'mundo', 'cruel', 'boton']\nlocalhost:8080\nen-us,en;q=0.5\n['localhost:8080', 'User-Agent', 'Accept', 'Accept-Language', 'Accept-Encoding', 'Accept-Charset', 'Keep-Alive', 'Connection', 'Referer']\n")

def run_test():                     
    TextTestRunner(verbosity=2).run(makeSuite(RondamonInterpretTetsCase))
    
if __name__ == '__main__':
    run_test()
    
